/*
 * ©2009-2018 南京擎盾信息科技有限公司 All rights reserved.
 */
package com.wuhao.code.check

import com.intellij.lang.jvm.JvmAnnotatedElement
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl
import com.intellij.psi.PsiElement
import com.intellij.util.PlatformUtils
import org.jetbrains.kotlin.asJava.toLightAnnotation
import org.jetbrains.kotlin.nj2k.postProcessing.resolve
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClass

/** 实际类型 */
val KtTypeElement.actualType: KtTypeElement?
  get() {
    return if (this is KtNullableType) {
      this.innerType
    } else {
      this
    }
  }

/**  是否idea */
val isIdea: Boolean
  get() {
    return PlatformUtils.isIdeaCommunity() || PlatformUtils.isIdeaUltimate()
  }

/** 是否启用了kotlin模块 */
val kotlinEnabled = try {
  Class.forName("org.jetbrains.kotlin.idea.KotlinLanguage")
  true
} catch (e: ClassNotFoundException) {
  false
}

/**  和当前元素并列的后一个元素 */
val PsiElement.next: PsiElement?
  get() = this.nextSibling

/**
 * @return
 */
fun KtTypeElement.resolveKtClass(): PsiElement? {
  if (this is KtUserType) {
    val resolved = this.referenceExpression?.resolve()
    return if (resolved is KtPrimaryConstructor) {
      resolved.containingClass()
    } else {
      resolved
    }
  }
  return null
}

/**
 * @param annoClass
 * @param propertyName
 * @return
 */
fun PsiElement.getStringListAnnotationValue(
    annoClass: String,
    propertyName: String = "value"
): List<String> {
  return when (this) {
    is KtAnnotated         -> this.getKtElStringListAnnotationValue(annoClass, propertyName)
    is JvmAnnotatedElement -> this.getJavaElStringListAnnotationValue(annoClass, propertyName)
    else                   -> listOf()
  }
}

/**
 * 判断kotlin元素上指定名称的注解
 * @param annotation 指定注解名称
 * @return
 */
fun KtAnnotated.getAnnotation(annotation: String): KtAnnotationEntry? {
  return this.annotationEntries.firstOrNull { it.toLightAnnotation()?.qualifiedName == annotation }
}


/**  获取目录下所有缓存的文件 */
val VirtualDirectoryImpl.cachedPosterity: ArrayList<VirtualFile>
  get() {
    val list = ArrayList<VirtualFile>()
    getCachedChildren(list, this)
    return list
  }


/**
 *
 * @param list
 * @param virtualDirectoryImpl
 */
private fun getCachedChildren(list: ArrayList<VirtualFile>, virtualDirectoryImpl: VirtualDirectoryImpl) {
  list.addAll(virtualDirectoryImpl.cachedChildren.filter { !it.isDirectory })
  virtualDirectoryImpl.cachedChildren.filterIsInstance<VirtualDirectoryImpl>()
      .forEach {
        getCachedChildren(list, it)
      }
}

/**
 * @param annotation
 * @return
 */
fun PsiElement.hasAnnotation(annotation: String): Boolean {
  if (this is KtAnnotated) {
    return this.annotationEntries.any { it.toLightAnnotation()?.qualifiedName == annotation }
  } else if (this is JvmAnnotatedElement) {
    return this.hasAnnotation(annotation)
  }
  return false
}

/**
 * @param annotations
 * @return
 */
fun PsiElement.hasAnyAnnotation(vararg annotations: String): Boolean {
  return annotations.any { this.hasAnnotation(it) }
}

/**
 * @param annotation
 * @return
 */
fun PsiElement.hasAnnotation(annotation: Class<*>): Boolean {
  return this.hasAnnotation(annotation.name)
}

